本文属于乱侃,其中语言可能包含语句不通甚至颠三倒四前后不搭的部分。如引起各位看官的不适请见谅
于是 Array.prototype.flatten
终于变成 Array.prototype.flat
了:https://github.com/tc39/propo...。方法名变成了一个名词或形容词。
我相信这不是标准制定者所情愿的(虽然有人 强行 解释了一下)。万恶之源就是这个叫做 Mootools 的库。我没有用过,但是听说在多年以前的国外被广泛使用。我不想细谈其内部细节,有兴趣的可以看谷歌的这篇博文:https://developers.google.com...
其实类似事情之前就发生过一次。问题出在同一个库身上,相同的解决方案:Array.prototype.contains
最终变成了 Array.prototype.includes
所谓兼容性就是抗历史包袱。如果一个新版本浏览器发布导致用户经常浏览的网站挂掉,他们不会认为这是网站的不对——他们根本不知道类似 Mootools
这种奇葩的存在。他们只知道:我原来用得好好的,怎么升级之后就坏了?从而加固“跟新有风险,升级需谨慎”的印象,甚至形成“升级恐惧症”。
其他语言或多或少都有一些历史包袱,异常沉重的有如 C++,但是这类编译型语言一旦被编译为目标代码,兼容性包袱便转抛给了操作系统。而前端代码不一样,他们被浏览器下载到了客户端解释(或预编译)执行,语言级别的包袱会一直持续下去。语言设计者们已经做过了尝试,比如这个神奇的 'use strict'
,但是它永远不可能默认开启。
所以 Mootools
那帮人在私自扩展原生对象的原型属性时,有没有想到着可能是一件会阻碍人类文明的发展进程的严重问题呢?
还是补充说明这次 smoothgate 事件的缘由。
Firefox 基于 Array.prototype.flatten 提议(旧版本,现在已经改为 flat)发布了支持该 API 的新版浏览器,导致了至少一个著名站点出现了异常。
Firefox 提供的 Array.prototype.flatten
实现并没有 bug,问题在于网站使用的一个叫 Mootools 的库。它提供了自己 非标准的 Array.prototype.flatten
版本实现。
Array.prototype.flatten = /* 非标准实现 */;
Mootools
提供的实现跟标准不同,然而这不是问题所在。Mootools
会强制覆盖浏览器原生的 Array.prototype.flatten
实现,依赖 Mootools
的 Array.prototype.flatten
实现的网站并不会因为原生版本和 Mootools
版本不一致而产生问题。
然而不幸的是 Mootools
还做了一件恶心的事情:它会把所有自定义的 Array.prototype
下方法实现复制到 Elements.prototype
下(Elements
是 Mootools
提供的自定义 API)。
for (var key in Array.prototype) {
Elements.prototype[key] = Array.prototype[key];
}
for-in
循环只会遍历 可枚举的(enumerable)的属性,例如 Array.prototype.sort
、Array.prototype.push
这些原生的方法都是默认不可枚举的(enumerable: false
),新的 Array.prototype.flatten
同样如此。Mootools
用自己的实现覆盖了原生的 Array.prototype.flatten
,但是并没有改变方法的 enumerable
属性——Array.prototype.flatten
仍然是不可枚举的,导致 Array.prototype.flatten
不会被复制到 Elements.prototype
下。
于是:所有依赖 Elements.prototype.flatten
的代码全部挂掉了。有人在 TC39 的官方 github 仓库发了个 PR 戏谑说建议把 flatten
改名为 smooth
,引发大讨论,甚至有人信以为真导致事件越发扩大。于是 Google Update 官博专门发文辟谣。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。